<template>
  <div>
    <!-- 角色搜索 -->
    <el-card shadow="always" style="height: 80px; margin-bottom: 20px">
      <el-form :inline="true" class="form">
        <el-form-item label="角色名：" style="width: 40%">
          <el-input placeholder="请输入搜索角色" v-model="keyWord"></el-input>
        </el-form-item>
        <!-- 搜索和重置按钮 -->
        <el-form-item>
          <el-button
            type="primary"
            :disabled="keyWord ? false : true"
            @click="searchRole"
          >
            搜索
          </el-button>
          <el-button @click="refreshRole">重置</el-button>
        </el-form-item>
      </el-form>
    </el-card>
    <!-- 表单列表 -->
    <el-card>
      <!-- 按钮 -->
      <el-button type="primary" icon="Plus" @click="addRole">
        添加角色
      </el-button>

      <!-- 内容表格 -->
      <!-- selection-change	当选择项发生变化时会触发该事件 -->
      <el-table style="margin: 10px 0" border :data="allRoleArr">
        <el-table-column
          label="#"
          align="center"
          type="index"
        ></el-table-column>
        <el-table-column label="ID" align="center" prop="id"></el-table-column>
        <el-table-column
          label="角色名称"
          align="center"
          prop="roleName"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="创建时间"
          align="center"
          prop="createTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column
          label="更新时间"
          align="center"
          prop="updateTime"
          show-overflow-tooltip
        ></el-table-column>
        <el-table-column label="操作" width="300px" align="center">
          <template #="{ row, $index }">
            <el-button
              plain
              icon="User"
              size="small"
              @click="setPermisstion(row)"
            >
              分配权限
            </el-button>
            <el-button
              type="primary"
              icon="Edit"
              size="small"
              @click="updateRole(row)"
            >
              编辑
            </el-button>
            <!-- 删除按钮 添加弹窗 -->
            <el-popconfirm
              :title="`你确定要删除${row.roleName}吗？`"
              @confirm="delRole(row.id)"
            >
              <template #reference>
                <el-button type="danger" icon="Delete" size="small">
                  删除
                </el-button>
              </template>
            </el-popconfirm>
          </template>
        </el-table-column>
      </el-table>
      <!-- 分页器 -->
      <el-pagination
        v-model:currentPage="pageNow"
        v-model:page-size="pageSize"
        :page-sizes="[5, 7, 9, 11]"
        :background="true"
        layout="prev, pager, next, jumper, ->, sizes, total"
        :total="total"
        @size-change="handler"
        @current-change="getHasRole"
      />
    </el-card>
    <!-- 点击添加角色的弹出框 -->
    <el-dialog
      v-model="dialogVisible"
      :title="addNewRole.id ? '修改角色' : '添加角色'"
      width="50%"
    >
      <template #default>
        <el-form :model="addNewRole" :rules="rules" ref="formRef">
          <el-form-item label="职位名称" prop="roleName">
            <el-input
              v-model="addNewRole.roleName"
              placeholder="请输入角色名称"
            />
          </el-form-item>
        </el-form>
      </template>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="cancel">取消</el-button>
          <el-button type="primary" @click="confirm">确定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 权限分配按钮 点击出现抽屉 -->
    <el-drawer v-model="drawer">
      <template #header>
        <h4>分配菜单和按钮的权限</h4>
      </template>
      <!-- 多选框 -->
      <template #default>
        <!-- 树形控件  
          default-expand-all :默认全部展开
          default-checked-keys ： 默认当前已被勾选的
        -->
        <el-tree
          ref="tree"
          :data="menuArr"
          show-checkbox
          node-key="id"
          default-expand-all
          :default-checked-keys="selectArr"
          :props="defaultProps"
        />
      </template>
      <template #footer>
        <div style="flex: auto">
          <el-button @click="drawer = false">取消</el-button>
          <el-button type="primary" @click="handlerRole">确认</el-button>
        </div>
      </template>
    </el-drawer>
  </div>
</template>

<script setup lang="ts">
import {
  reqAllRole,
  reqAddOrUpdate,
  reqDelRole,
  reqAllMenuList,
  reqSetPermisstion,
} from '@/api/acl/role/index'
import type {
  AllRoleData,
  Records,
  RoleData,
  MenuResponseData,
  MenuList,
} from '@/api/acl/role/type'
import { ElMessage } from 'element-plus'
import { ref, onMounted, reactive, nextTick } from 'vue'
import useLayOutSettingStore from '@/store/modules/setting'

// 存放当前页
const pageNow = ref<number>(1)
// 当前页有几条数据
const pageSize = ref<number>(5)
// 收集总条数
const total = ref<number>(0)
// 存放所有角色的数组
const allRoleArr = ref<Records>([])
// 添加角色弹出框
const dialogVisible = ref<boolean>(false)
// 收集新添加的角色
const addNewRole = reactive<RoleData>({
  roleName: '',
})
// 弹窗表单的校验
const formRef = ref<any>()

// 获取所有角色列表
const getHasRole = async () => {
  const res: AllRoleData = await reqAllRole(
    pageNow.value,
    pageSize.value,
    keyWord.value,
  )
  if (res.code == 200) {
    allRoleArr.value = res.data.records
    total.value = res.data.total
  }
}
// 分页器下拉框
const handler = () => {
  getHasRole()
}
// 页面挂载就渲染数据
onMounted(() => {
  getHasRole()
})
// 给添加按钮增加点击事件 点击弹出对话框
const addRole = () => {
  // 弹出添加框
  dialogVisible.value = true
  // 每次添加的时候要保证上一次在抽屉里写的东西被清除
  Object.assign(addNewRole, {
    roleName: '',
    id: 0, //因为编辑的时候会存有id  所以这里也要清除掉
  })
  //先点击编辑按钮 再点击添加 会出现抽屉表单校验报错还存在的情况 因为第一次我们拿不到抽屉的form表单 是underfind 所以我们要点击的时候 先获取一下更新后的dom
  // 清除一下form表单的校验
  nextTick(() => {
    formRef.value.clearValidate('roleName')
  })
}
// 编辑按钮 事件
const updateRole = (row: RoleData) => {
  dialogVisible.value = true
  // 存储已有的角色信息
  Object.assign(addNewRole, row)
  //先点击编辑按钮 再点击添加 会出现抽屉表单校验报错还存在的情况 因为第一次我们拿不到抽屉的form表单 是underfind 所以我们要点击的时候 先获取一下更新后的dom
  // 清除一下form表单的校验
  nextTick(() => {
    formRef.value.clearValidate('roleName')
  })
}
// 弹出框的确认按钮
const confirm = async () => {
  // 确认提交前 要对整个form表单进行校验 校验通过了 才继续往下调用接口
  await formRef.value.validate()
  // 获取新增或修改角色接口
  const res: any = await reqAddOrUpdate(addNewRole)
  if (res.code == 200) {
    ElMessage({
      type: 'success',
      message: addNewRole.id ? '修改成功' : '添加成功',
    })
    // 重新获取列表
    getHasRole()
  } else {
    ElMessage({
      type: 'error',
      message: addNewRole.id ? '修改失败' : '添加失败',
    })
  }
  dialogVisible.value = false
}
// 弹出框的取消按钮
const cancel = () => {
  dialogVisible.value = false
}
// 自定义校验
const validateRoleName = (rule: any, value: any, callback: any) => {
  if (value.trim().length >= 2) {
    callback()
  } else {
    callback(new Error('长度不能小于2位'))
  }
}
// 弹出框的表单校验
const rules = {
  roleName: [{ required: true, trigger: 'blur', validator: validateRoleName }],
}
// 操作里的删除按钮
const delRole = async (id: string) => {
  const res = await reqDelRole(id)
  if (res.code == 200) {
    ElMessage({ type: 'success', message: '删除成功' })
    getHasRole()
  }
}
// ///////////////////////////////////////////////////////搜索部分
// 搜索角色添加一个关键词
const keyWord = ref<string>('')
// 搜索角色按钮
const searchRole = () => {
  // 重新调用列表接口
  getHasRole()
}

// 重置按钮 也是调用setting小仓库里的更新值 变化了就重新加载
const settingStore = useLayOutSettingStore()
const refreshRole = () => {
  settingStore.refresh = !settingStore.refresh
}
// -----------------------------------------------------------------抽屉部分
// 抽屉是否显示
const drawer = ref<boolean>(false)
// 存储抽屉里 接口获取到的菜单数据
const menuArr = ref<MenuList>([])
// 定义一个数组 来存放勾选展示四级id
const selectArr = ref<number[]>([])
// 定义树形控件组件实例 也就是选中的id
const tree = ref<any>()
// 定义一个数组
// 分配权限按钮
const setPermisstion = async (row: RoleData) => {
  drawer.value = true
  Object.assign(addNewRole, row)
  // 获取到相应的接口数据
  const res: MenuResponseData = await reqAllMenuList(addNewRole.id as number)
  // console.log(res);
  menuArr.value = res.data
  // 调用过滤方法 过滤接口得到四级分组里面 select为true的选项id 放在一个数组里
  // filterSelectArr(menuArr.value,[])
  // 将过滤得到的数组赋值给存放数组
  selectArr.value = filterSelectArr(menuArr.value, [])
}
// 多选框的数组
const defaultProps = {
  children: 'children', //菜单数据里的儿子数组
  label: 'name', //菜单数据里的名字
}
// 定义一个方法 过滤接口得到四级分组里面 select为true的选项id
const filterSelectArr = (allData: any, intaArr: any) => {
  // console.log(allData);
  // 先将数组遍历
  allData.forEach((item: any) => {
    // 如果这个数组里每一项的select为真且它的层级为4  就把这一项的id 放进数组intaArr里
    if (item.select && item.level == 4) {
      intaArr.push(item.id)
    }
    // 继续进行递归 如果有儿子并且儿子的长度大于0  继续往下进行筛选
    if (item.children && item.children.length > 0) {
      filterSelectArr(item.children, intaArr)
    }
  })
  // 最终返回这个数组
  return intaArr
}
// 抽屉确定按钮
const handlerRole = async () => {
  // 获取到这个当前职位或者角色的id
  const roleId = addNewRole.id as number
  // 选中的节点id
  let arr = tree.value.getCheckedKeys() //getCheckedKeys 若节点可用被选中 它将返回当前选中节点 key 的数组
  // 半选节点的id 就是选中节点的父亲
  let arr1 = tree.value.getHalfCheckedKeys() //getHalfCheckedKeys 如果节点可用被选中 它将返回当前半选中的节点组成的数组
  // console.log(arr);
  // console.log(arr1);
  // 将拿到的两个数组合并
  let permisstionId = arr.concat(arr1)
  // 下发权限 就是请求接口
  const res: any = await reqSetPermisstion(roleId, permisstionId)
  // console.log(res);
  if (res.code == 200) {
    drawer.value = false
    ElMessage({ type: 'success', message: '分配权限成功' })
    // 页面刷新
    window.location.reload()
  }
}
</script>

<style scoped lang="scss">
.form {
  display: flex;
  justify-content: space-between;
  align-items: center;
}
</style>
